--------------------------------------------------------------------
-- This is test code for coremoter
-- It shows you how to accept accelerometer and tuner events in your app
-- It also shows how to create a textfield in you app
-- You can run this code in the corona simulator
-- You can also build it for device with no code line changed
-- Pay attention to the "code change:" parts, those are modifications you should made to your code
-- 
-- By Wei Hua, 2011
--------------------------------------------------------------------

-- This must be required to use remoter interface
local	remoter	= require("remoter")
--------------------------------------------------------------------
-- code change:
--------------------------------------------------------------------
-- remoter.startService must be called before any use of remoter
print("startService: "..tostring(remoter.startService("udp", 1974)))
-- if you want to start a TCP server, just use the following code
--remoter.startService()

local	physics	= require("physics")

display.setStatusBar( display.HiddenStatusBar ) 
system.activate( "multitouch" )
physics.start(true)

-- following code is to test Accelerometer
-- it builds a box with 4 walls and a ball in it
-- it alos shows a gravity indicator to represent the gravity changes vividly
local	w,h	= display.contentWidth, display.contentHeight
local	top	= display.newRect(0,0,w,4)
top:setFillColor(0,200,0)
physics.addBody(top, "static")
local	bottom	= display.newRect(0,h-4,w,4)
bottom:setFillColor(0,200,0)
physics.addBody(bottom, "static")
local	left	= display.newRect(0,0,4,h)
left:setFillColor(0,200,0)
physics.addBody(left, "static")
local	right	= display.newRect(w-4,0,4,h)
right:setFillColor(0,200,0)
physics.addBody(right, "static")

-- test for drag a ball

-- focus on one event
local	circle	= display.newCircle(w/2-50,h/2-50,50)
circle:setFillColor(255,100,0,200)
physics.addBody(circle, { density = 1.0, friction = 0.3, bounce = 0.2, radius = 50, linearDamping=2 })
function circle:touch(event)
	if( event.phase=="moved" ) then
		-- follow the touch point
		if( self._dragjoint ) then
			self._dragjoint:setTarget(event.x, event.y)
		end
	elseif( event.phase=="began" ) then
		-- focus on this event
		display.getCurrentStage():setFocus(self, event.id)
		-- create a touch joint
		self._dragjoint	= physics.newJoint("touch", self, event.x, event.y)
		self._dragjoint.maxForce	= 200
	elseif( event.phase=="ended" or event.phase=="cancelled" ) then
		if( self._dragjoint ) then
			display.getCurrentStage():setFocus(self, nil)
			self._dragjoint:removeSelf()
			self._dragjoint	= nil
			if( self._dl ) then
				self._dl:removeSelf()
				self._dl	= nil
			end
		end
	end
	return	true
end
circle:addEventListener("touch", circle)

local	circle1	= display.newCircle(w/2-50,h/2-50,50)
circle1:setFillColor(255,100,0,200)
physics.addBody(circle1, { density = 1.0, friction = 0.3, bounce = 0.2, radius = 50, linearDamping=2 })
function circle1:touch(event)
	if( event.phase=="moved" ) then
		-- follow the touch point
		if( self._dragjoint ) then
			self._dragjoint:setTarget(event.x, event.y)
		end
	elseif( event.phase=="began" ) then
		-- focus on this event
		display.getCurrentStage():setFocus(self, event.id)
		-- create a touch joint
		self._dragjoint	= physics.newJoint("touch", self, event.x, event.y)
		self._dragjoint.maxForce	= 200
	elseif( event.phase=="ended" or event.phase=="cancelled" ) then
		if( self._dragjoint ) then
			display.getCurrentStage():setFocus(self, nil)
			self._dragjoint:removeSelf()
			self._dragjoint	= nil
			if( self._dl ) then
				self._dl:removeSelf()
				self._dl	= nil
			end
		end
	end
	return	true
end
circle1:addEventListener("touch", circle1)

-- global focus
local	circle2	= display.newCircle(w/2+50,h/2,50)
circle2:setFillColor(100,255,0,200)
circle2:setStrokeColor(255,255,255,200)
circle2.strokeWidth	= 8
circle2._dragjoint	= {}
circle2._jnum		= 0
physics.addBody(circle2, { density = 1.0, friction = 0.3, bounce = 0.2, radius = 50, linearDamping=2 })
function circle2:touch(event)
	local	j	= self._dragjoint[event.id]
	if( event.phase=="moved" ) then
		-- follow the touch point
		if( j ) then
			j.j:setTarget(event.x, event.y)
		end
	elseif( event.phase=="began" ) then
		if( self._jnum==0 ) then
			-- focus on this event
			display.getCurrentStage():setFocus(self)
		end
		-- create a touch joint
		j	= {}
		j.j	= physics.newJoint("touch", self, event.x, event.y)
		j.j.maxForce	= 200
		self._dragjoint[event.id]	= j
		self._jnum	= self._jnum + 1
	elseif( event.phase=="ended" or event.phase=="cancelled" ) then
		if( j ) then
			if( j._dl ) then
				j._dl:removeSelf()
				j._dl	= nil
			end
			j.j:removeSelf()
			self._dragjoint[event.id]	= nil
			self._jnum	= self._jnum - 1
			if( self._jnum==0 ) then
				-- focus on this event
				display.getCurrentStage():setFocus(nil)
			end
		end
	end
	return	true
end
circle2:addEventListener("touch", circle2)


-- gravity indicator
lineGravity		= nil
tipGravity		= nil
function onTilt( event )
	-- remove old line
	if( lineGravity ) then
		lineGravity:removeSelf()
		tipGravity:removeSelf()
	end
	local	scale	= 100
	local	p1x	= 150
	local	p1y	= 150
	local	p2x	= p1x+event.xGravity*scale
	local	p2y	= p1y-event.yGravity*scale
	lineGravity	= display.newLine(p1x,p1y,p2x,p2y)
	lineGravity:setColor(0,255,0,200)
	lineGravity.width	= 4
	tipGravity	= display.newCircle(p2x,p2y,lineGravity.width+2)
	tipGravity:setFillColor(255,255,0,200)

	if( math.abs(event.xGravity)<0.05 and math.abs(event.yGravity)<0.05 ) then
		physics.setGravity( 0, 0 )
	else
		physics.setGravity( ( 9.8 * event.xGravity ), ( -9.8 * event.yGravity ) )
		if( g_bIsShake ~= event.isShake ) then
			g_bIsShake	= event.isShake
			if( g_bIsShake ) then
				print("**** shaking ...")
			end
		end
	end
end

Runtime:addEventListener("accelerometer", onTilt)

-- test for multiple accelerometer event handler (touch the gravity text to activate it)
local a2on = true
local t	= display.newText('',150,20,native.systemFont,16)
t.text	= 'gravity'
function a2listener(event)
	t.text=event.xGravity..","..event.yGravity
end
function t:touch(event)
	if( event.phase=="began" ) then
		a2on	= not a2on
		if( a2on ) then
			Runtime:addEventListener("accelerometer", a2listener)
		else
			Runtime:removeEventListener("accelerometer", a2listener)
		end
	end
	return	true
end
t:addEventListener("touch", t)
Runtime:addEventListener("accelerometer", a2listener)

-- compass indicator
local compass_arrow	= display.newGroup()
local _arrow		= display.newLine(0,20, -10,30)
_arrow:append( -10,-20, -20,-20, 0,-40, 20,-20, 10,-20, 10,30, 0,20)
_arrow:setColor( 100, 255, 0, 128 )
_arrow.width 	= 4
compass_arrow:insert(_arrow)
compass_arrow.x,compass_arrow.y	= 150,350
compass_arrow.isVisible	= false
-- check if no heading event was sent for a long time
local te_chk_heading_event	= nil
local lastHeadingEventTime	= 0
local function headingHandler(event)
	lastHeadingEventTime	= system.getTimer()
	-- create a check event if there is no such one
	local function _chk()
		if( system.getTimer() - lastHeadingEventTime > 2000 ) then
			-- hide the arrow
			compass_arrow.isVisible	= false
			-- cancel the chk event
			timer.cancel(te_chk_heading_event)
			te_chk_heading_event	= nil
		end
	end
	if( not te_chk_heading_event ) then
		te_chk_heading_event	= timer.performWithDelay(2000, _chk, 0)
		-- show the arrow
		compass_arrow.isVisible	= true
	end
	-- adjust the arrow to compass direction
	--compass_arrow.rotation		= -event.geographic
	compass_arrow.rotation		= -event.magnetic
end
Runtime:addEventListener("heading", headingHandler)

-- GPS indicator
local gpstext	= display.newText('', 150,50,native.systemFont,16)
gpstext.text	= 'GPS'
local function locationHandler(event)
	-- just show the position info
	gpstext.text	= 'GPS lat:'..event.latitude..' lon:'..event.longitude..' alt:'..event.altitude
end
Runtime:addEventListener("location", locationHandler)

-- lable to display input content
local	lbinput		= remoter.createLable({text=display.contentWidth..'x'..display.contentHeight,x=100,y=100,w=150,h=22})
-- create an input textfield
--[[ test for function
local	function tf_func(event)
	if( event.phase=="submitted" ) then
		lbinput:setText(iptf1.text.." "..iptf2.text)
		--native.setKeyboardFocus(nil)
	end
end
--------------------------------------------------------------------
-- code change:
--------------------------------------------------------------------
iptf1	= remoter.createTextField({text="[input1]",x=100,y=200,w=100,h=22},tf_func)
iptf2	= remoter.createTextField({text="[input2]",x=100,y=250,w=100,h=22},tf_func)
--]]
-- test for listener object
local	function tf_func(self, event)
	if( event.phase=="submitted" ) then
		lbinput:setText("sub:"..self.text.text)
		-- native.setKeyboardFocus(nil) -- no need for these
	elseif( event.phase=="ended" ) then
		lbinput:setText("end:"..self.text.text)
	end
end
local	iptf1_l	= {userInput=tf_func}
local	iptf2_l	= {userInput=tf_func}
--------------------------------------------------------------------
-- code change:
--------------------------------------------------------------------
-- this is the way to create a textfield
iptf1	= remoter.createTextField({text="[input1]",x=100,y=200,w=100,h=22},iptf1_l)
iptf2	= remoter.createTextField({text="[input2]",x=100,y=250,w=100,h=22},iptf2_l)
iptf1_l.text	= iptf1
iptf2_l.text	= iptf2

local	lb		= remoter.createLable({text="time",x=100,y=130,w=100,h=22})
local	count=0
local	function ef(event)
	count=count+1;
	lb:setText(count);
	createTunerCircle(remoter.getTunerFrequency(),remoter.getTunerVolume())
	-- draw the drag lines
	if( circle._dragjoint ) then
		local	j	= circle._dragjoint
		if( circle._dl ) then
			circle._dl:removeSelf()
			circle._dl	= nil
		end
		local x,y	= j:getAnchorA()
		local xb,yb	= j:getAnchorB()
		local	dl	= display.newLine(x,y,xb,yb)
		dl.width	= 4
		dl:setColor(255,0,0,200)
		circle._dl	= dl
	end
	if( circle1._dragjoint ) then
		local	j	= circle1._dragjoint
		if( circle1._dl ) then
			circle1._dl:removeSelf()
			circle1._dl	= nil
		end
		local x,y	= j:getAnchorA()
		local xb,yb	= j:getAnchorB()
		local	dl	= display.newLine(x,y,xb,yb)
		dl.width	= 4
		dl:setColor(255,0,0,200)
		circle1._dl	= dl
	end
	if( circle2._jnum>0 ) then
		for id,j in pairs(circle2._dragjoint) do
			if( j._dl ) then
				j._dl:removeSelf()
				j._dl	= nil
			end
			local x,y	= j.j:getAnchorA()
			local xb,yb	= j.j:getAnchorB()
			local	dl	= display.newLine(x,y,xb,yb)
			dl.width	= 4
			dl:setColor(255,0,0,200)
			j._dl	= dl
		end
	end
end
Runtime:addEventListener("enterFrame", ef)

--------------------------------------------------------------------
-- code change:
--------------------------------------------------------------------
-- use remoter.startTuner() to receive tuner data
remoter.startTuner()

-- to demo tuner (volume and frequence changes)
local	g_TunerCircle	= display.newGroup()
g_TunerCircle.x			= display.contentWidth/2
g_TunerCircle.y			= display.contentHeight*2/3

function createTunerCircle(freq,vol,timeout)
	if( freq==0 ) then
		return;
	end
	if( not timeout ) then timeout=100 end
	local	c	= display.newCircle(0,0, (vol-0.4)*200)
	g_TunerCircle:insert(c)
	freq		= math.floor(freq/2)
	if( freq>255 ) then freq=255 end
	c:setFillColor(freq,255-freq,0,128)
	-- set fade out
	transition.to(c, {alpha=0, time=timeout, onComplete=function(obj) g_TunerCircle:remove(c); end})
	return	c
end

-- global touch test
local	rcolor	= {
	{255,0,0,255},
	{0,255,0,255},
	{0,0,255,255},
}
local	rcidx	= 1
local function gtouch(event)
	-- create a transition rect
	local	r	= display.newRect(event.x-20,event.y-20,40,40)
	local	c	= rcolor[rcidx]
	rcidx		= rcidx+1
	if( rcidx>#rcolor ) then rcidx=1 end
	r:setFillColor(c[1], c[2], c[3], c[4])
	transition.to(r, {time=500, rotation=180, alpha=0, xScale=0.1, yScale=0.1, onComplete=function(obj) obj:removeSelf(c); end})
end
Runtime:addEventListener("touch", gtouch)
